package cg

import (
	"encoding/json"
	"errors"
	"sync"

	"game/ipc"
)

var _ ipc.Server = &CenterServer{} // 确定实现了Server接口

type Message struct {
	From    string
	To      string
	Content string
}

type CenterServer struct {
	servers map[string]ipc.Server
	players []*Player
	multex  sync.RWMutex
}

func NewCenterServer() *CenterServer {
	servers := make(map[string]ipc.Server)
	players := make([]*Player, 0)

	return &CenterServer{servers: servers, players: players}
}

func (server *CenterServer) AddPlayer(params string) error {

	player := NewPlayer()

	err := json.Unmarshal([]byte(params), &player)

	if err != nil {
		return err
	}

	server.multex.Lock()

	defer server.multex.Unlock()

	server.players = append(server.players, player)

	return nil

}

func (server *CenterServer) removePlayer(params string) error {

	server.multex.Lock()

	defer server.multex.Unlock()

	for i, v := range server.players {

		if v.Name == params {

			if len(server.players) == 1 {

				server.players = make([]*Player, 0)

			} else if i == len(server.players)-1 {

				server.players = server.players[:i-1]

			} else if i == 0 {

				server.players = server.players[1:]

			} else {

				server.players = append(server.players[:i-1], server.players[:i+1]...)

			}

			return nil
		}

	}

	return errors.New("Player not found !")

}

func (server *CenterServer) listPlayer() (players string, err error) {

	server.multex.RLock()

	defer server.multex.RUnlock()

	if len(server.players) > 0 {
		str, _ := json.Marshal(server.players)
		players = string(str)
	} else {
		err = errors.New("No Player Online")
	}

	return

}

func (server *CenterServer) broadcast(params string) error {
	var message Message
	err := json.Unmarshal([]byte(params), &message)

	if err != nil {
		return err
	}

	server.multex.Lock()
	defer server.multex.Unlock()

	if len(server.players) > 0 {
		for _, player := range server.players {
			player.ms <- &message
		}
	} else {
		err = errors.New("No Player online !")
	}
	return err
}

func (server *CenterServer) Handle(method, params string) *ipc.Response {
	switch method {
	case "addplayer":
		err := server.AddPlayer(params)
		if err != nil {
			return &ipc.Response{Code: err.Error()}
		}
	case "removeplayer":
		err := server.removePlayer(params)

		if err != nil {
			return &ipc.Response{Code: err.Error()}
		}

		return &ipc.Response{Code: "200"}
	case "listplayer":
		players, err := server.listPlayer()
		if err != nil {
			return &ipc.Response{Code: err.Error()}
		}
		return &ipc.Response{Code: "200", Body: players}
	case "broadcast":
		err := server.broadcast(params)
		if err != nil {
			return &ipc.Response{Code: err.Error()}
		}
		return &ipc.Response{Code: "200"}
	default:
		return &ipc.Response{Code: "404", Body: method + ":" + params}
	}

	return &ipc.Response{Code: "200"}
}

func (server *CenterServer) Name() string {
	return "CenterServer"
}
